import * as TOOL from "../tool"
import { DataSegment } from "../../datastructure/DataSegment";
import { MapBar } from "../map_bar/MapBar";
export class ChatBar {
    constructor(element?: Element | string | null | undefined) {
        this.element = TOOL.creatElement(element);
        this.onlineStatus = new OnlineStatus();
        this.inPut = new Input();
        this.chatLog = new ChatLog();
        this.element.appendChild(this.onlineStatus.element);
        this.element.appendChild(this.inPut.element);
        this.element.appendChild(this.chatLog.element);
    }

    public resize(height: number, width: number) {
        this.height = height * 1;
        this.width = width * 0.2;
        this.element!.style.height = this.height + "px";
        this.element!.style.width = this.width + "px";
        this.element!.style.top = "0";
        this.element!.style.left = width - this.width + "px";
        this.onlineStatus.resize(this.height, this.width);
        this.inPut.resize(this.height, this.width);
        this.chatLog.resize(this.height, this.width);
    }

    public addChatItem(item: ChatLogItem) {
        this.chatLog.add(item);
    }

    public onChat(message: DataSegment) {
        let from = message.get("from") as string;
        let data = message.get("data") as string;
        let serial = message.get("serial") as string;
        let item = new ChatLogItem(from, data, serial);
        this.addChatItem(item);
    }

    public onInstruct(message: DataSegment) {
        let color = message.get("color") as string;
        let data = message.get("data") as string;
        let serial = message.get("serial") as string;
        this.addChatItem(new ChatInfoItem(data, color, serial));
    }

    public onOnline(message: DataSegment) {
        let what = message.get("what") as string;
        let who = message.get("who") as string;
        switch (what) {
            case "new_user":
                this.addChatItem(new ChatInfoItem(who + "已加入", "secondary"));
                this.onlineStatus.addPlayer(who);
                break;
            case "user_leave":
                this.addChatItem(new ChatInfoItem(who + "已离开", "secondary"));
                this.onlineStatus.removePlayer(who);
                break;
            case "update_user_list":
                this.onlineStatus.setPlayers(message.get("players") as string[]);
                this.onlineStatus.setDm(message.get("dm") as string);
                break;
            case "current":
                this.chatLog.setLastSerial(parseInt(message.get("serial") as string));
                break;
        }
    }

    public onlineStatus: OnlineStatus;
    public inPut: Input;
    public chatLog: ChatLog;
    public element: HTMLElement;
    public height: number = 0;
    public width: number = 0;
}

export class OnlineStatus {
    constructor(element?: HTMLElement | string | null | undefined) {
        if (element instanceof HTMLElement) {
            this.element = element;
        } else if (typeof element == "string") {
            let e = document.querySelector(element) as HTMLElement;
            this.element = e ? e : TOOL.creatElement();
        } else {
            this.element = TOOL.creatElement();
        }
        this.element.style.overflowY = "scroll";
        this.element.style.overflowX = "hidden";

        this.dm = document.createElement("span");
        let dm_p = document.createElement("p");
        dm_p.style.marginBottom = "0px";
        dm_p.innerText = "DM:";
        dm_p.appendChild(this.dm);

        this.playersDOM = new Map();

        this.players = document.createElement("p");
        this.element.appendChild(dm_p);
        this.element.appendChild(this.players);
    }

    public resize(height: number, width: number) {
        this.height = height * 0.15;
        this.width = width;
        this.element!.style.height = this.height + "px";
        this.element!.style.width = this.width + "px";
        this.element!.style.top = "0";
        this.element!.style.left = "0";
    }

    public setDm(dm: string) {
        this.dm.innerHTML = "";
        this.dm.appendChild(TOOL.createBadge(dm));
    }

    public setPlayers(players: string[]) {
        this.players.innerHTML = "";
        for (let i = 0; i < players.length; i++) {
            this.addPlayer(players[i]);
        }
    }

    public addPlayer(player: string) {
        let badge = TOOL.createBadge(player);
        this.players.appendChild(badge);
        this.playersDOM.set(player, badge)
    }

    public removePlayer(player: string) {
        this.playersDOM.get(player)!.remove();
    }

    public element: HTMLElement;
    public height: number = 0;
    public width: number = 0;
    private dm: HTMLElement;
    private players: HTMLElement;
    private playersDOM: Map<string, HTMLElement>;
}

export class Input {
    constructor(element?: Element | string | null | undefined) {
        this.element = TOOL.creatElement();
        this.inputBox = document.createElement("textarea");
        this.inputBox.classList.add("form-control");
        this.inputBox.style.padding = "4px"
        this.inputBox.onkeypress = this.onKeyPress;

        this.button = document.createElement("button");
        this.button.setAttribute('type', 'button');
        this.button.innerHTML = "发送"
        this.button.classList.add("btn");
        this.button.classList.add("btn-primary");

        this.element.appendChild(this.button);
        this.element.appendChild(this.inputBox);
        this.button.onclick = this.onButtonClick;
    }

    public resize(height: number, width: number) {
        this.height = height * 0.2;
        this.width = width * 1;
        this.element!.style.height = this.height + "px";
        this.element!.style.width = this.width + "px";
        this.element!.style.top = height - this.height + "px";
        this.element!.style.left = "0";
        this.inputBox.style.height = this.height + "px";
        this.button.style.position = "absolute";
        this.button.style.top = this.height - this.button.offsetHeight - 5 + "px";
        this.button.style.left = this.width - this.button.offsetWidth - 5 + "px";
    }

    public sendChatMessage = (str: string) => { };
    public sendCommand = (str: string) => { };
    public sendLocalCommand = (str: string) => { };
    public element: HTMLElement;
    public inputBox: HTMLTextAreaElement;
    public button: HTMLElement;
    public height: number = 0;
    public width: number = 0;
    private onButtonClick = () => {
        let message = this.inputBox.value;
        if (!message)
            return;
        if (message[0] === '/') {
            let command = message.substr(1);
            if (MapBar.CONSOLE_COMMAND.has(command.split(" ")[0])) {
                this.sendLocalCommand(message.substr(1));
            } else {
                this.sendCommand(message.substr(1));
            }
        }
        else {
            this.sendChatMessage(message);
        }
        this.inputBox.value = "";
    }
    private onKeyPress = (ev: KeyboardEvent) => {
        let keyCode = ev.code;
        switch (keyCode) {
            case "Enter":
            case "NumpadEnter":
                this.button.click();
                return false;
            default:
                break;
        }
    }
}

export class ChatLog {
    constructor(element?: Element | string | null | undefined) {
        this.element = TOOL.creatElement();
        this.element.classList.add("card-block");
        this.element.style.overflowY = "scroll";
        this.element.style.overflowX = "hidden";
        this.button = document.createElement("button");
        this.button.setAttribute('type', 'button');
        this.button.innerHTML = "获取历史消息";
        this.button.classList.add("btn");
        this.button.classList.add("btn-primary");
        this.button.style.width = "100%";
        this.button.onclick = this.onButtonClick.bind(this);
    }

    public resize(height: number, width: number) {
        this.element!.style.height = height * 0.65 + "px";
        this.element!.style.width = width * 1 + "px";
        this.element!.style.top = height * 0.15 + "px";
        this.element!.style.left = "0";
    }

    public add(item: ChatLogItem | ChatInfoItem) {
        let id = parseInt(item.element.id);
        if (!id) {
            console.log("警告", item, "不包含序号id");
        } else {
            console.log("收到序号", id);
        }
        if (id < this.lastSerial) {
            console.log("收到了过去的消息,开始还原");
            this.lastSerial--;
            let next = document.getElementById((id + 1).toString());
            let insertBefore = next || this.element.firstChild;
            this.element.insertBefore(item.element, insertBefore);
            if (this.lastSerial > 0)
                this.element.insertBefore(this.button, this.element.firstChild);
        } else {
            this.element.appendChild(item.element);
            this.element.scrollTop = this.element.scrollHeight;
        }
    }

    public clear() {
        this.element.innerHTML = "";
    }

    public setLastSerial(serial: number) {
        this.lastSerial = serial;
        if (this.lastSerial > 0)
            this.element.insertBefore(this.button, this.element.firstChild);
    }
    public sendOnline = (serial: string) => { };
    private onButtonClick() {
        this.button.remove();
        console.log("获取", this.lastSerial - 1);
        this.sendOnline((this.lastSerial - 1).toString());
    }
    public element: HTMLElement;
    private lastSerial = 0; // 初始值是期望收到的下一条消息的 id
    private button: HTMLButtonElement;
}

export class ChatInfoItem {
    constructor(message: string, color?: string, serial?: string) {
        this.element = document.createElement("div");
        this.element.id = serial ? serial : "";
        let data = document.createElement("div");
        data.classList.add("card");
        if (color) {
            data.classList.add("bg-" + color);
        } else {
            data.classList.add("bg-warning");
        }
        data.classList.add("mb-3");
        data.classList.add("text-center");
        data.style.marginTop = "16px";
        data.style.marginBottom = "16px";

        let data_body = document.createElement("div");
        data_body.classList.add("card-body");
        data_body.style.paddingTop = "10px";
        data_body.style.paddingBottom = "10px";

        let text = document.createElement("p");
        text.classList.add("card-text");
        text.innerHTML = message;

        data_body.appendChild(text);
        data.appendChild(data_body);
        this.element.appendChild(data);
    }

    public element: HTMLElement;
}

export class ChatLogItem {
    constructor(from: string, message: string, serial?: string, color?: string) {
        this.element = document.createElement("div");
        this.element.id = serial ? serial : "";
        let name = TOOL.createBadge(from, color);
        let data = document.createElement("span");
        data.innerHTML = " : " + message;

        this.element.appendChild(name);
        this.element.appendChild(data);
    }

    public element: HTMLElement;
}

